Hands on with the AppStoreServerLibrary for Python

Henry Serrano Jan 11, 2024

It's been already over 3 weeks (at the time of this first edit) that Apple released its open source AppStoreServerLibrary for Python! Yay!

Why it matters? For starters, it already has all the required code for decoding AppStoreServer Notifications out of the box and it's really simple to use (although the current state of its documentation is a bit lacking). This is an amazing thing because it's now easier to decode notifications in just a small amount of lines of code!

Lucky for you, this post will cover on more focused examples on how and where you can start using it.

Some notes before getting started:

  • You need to have a valid developer account (personal or business)
  • You need to have a valid app with a bundleID registered
  • You will need to have access to AppStoreConnect to be able to edit the URL fields for AppStoreServer notifications.
  • If you don't have an app released you cannot test notifications being dispatched to your production URL.

An amazing place to host your URL endpoints is actually Google Cloud, specifically, by deploying a custom Function (not that any server or cloud provider that supports deploying Python on a server or via server less method will also work). It's quite simple to get started and you can follow up its official tutorial here.

Let's start by defining a custom method that builds a SignedDataVerifier (please READ CAREFULLY through the comments to make the values match your app data):

def build_signed_data_verifier():
    # Load all Apple certificates stored in the same bucket as this function.
    # Note that the certificates need to be loaded as byte strings ('rb').
    certificate_file = open("./AppleIncRootCertificate.cer", "rb") 
    main_certificate_1 = certificate_file.read()
    certificate_file.close()

    certificate_file = open("./AppleComputerRootCertificate.cer", "rb") 
    main_certificate_2 = certificate_file.read()
    certificate_file.close()

    certificate_file = open("./AppleRootCA-G2.cer", "rb") 
    main_certificate_3 = certificate_file.read()
    certificate_file.close()

    certificate_file = open("./AppleRootCA-G3.cer", "rb") 
    main_certificate_4 = certificate_file.read()
    certificate_file.close()

    # Put all the certificates in a list.
    root_certificates = [main_certificate_1, main_certificate_2, main_certificate_3, main_certificate_4]

    # Pass all the information to the SignedDataVerifier to properly decode the response.
    enable_online_checks = True

    # Update this string with your app's bundle id.
    bundle_id = ""

    # If your app is not released then change `PRODUCTION`` to `SANDBOX`.
    environment = Environment.PRODUCTION

    # You must update `app_apple_id` from the ID that Apple assigns to your app. If you don't
    # have one yet, remove/comment this variable and remove/comment it from the SignedDataVerifier
    # init.
    app_apple_id = 0
    
    return SignedDataVerifier(root_certificates, enable_online_checks, environment, bundle_id, app_apple_id)